/* eslint-disable*/
// Turn background objects into routing objects

import { cloneDeep, omit } from 'lodash-es';
import type { AppRouteModule, AppRouteRecordRaw } from '/#/route';
import type { Router, RouteRecordNormalized } from 'vue-router';
import { warn } from '/@/utils/log';
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
import { SaaSPageEnum } from '../../enums/pageEnum';
import { PAGE_NOT_FOUND_ROUTE } from '../routes/basic';
import { Menu } from '../../../types/route';

let dynamicViewsModules: Record<string, () => Promise<Recordable>>;

const LayoutMap = new Map<string, () => Promise<typeof import('*.vue')>>();
export const LAYOUT = () => import('/@/layout/default/index.vue');
LayoutMap.set('LAYOUT', LAYOUT);

function dynamicImport(dynamicViewsModules: Record<string, () => Promise<Recordable>>, component: string) {
  const keys = Object.keys(dynamicViewsModules);
  const matchKeys = keys.filter((key) => {
    const k = key.replace('../../views', '');
    const startFlag = component.startsWith('/');
    const endFlag = component.endsWith('.vue') || component.endsWith('.tsx');
    const startIndex = startFlag ? 0 : 1;
    const lastIndex = endFlag ? k.length : k.lastIndexOf('.');
    return k.substring(startIndex, lastIndex) === component;
  });
  if (matchKeys?.length === 1) {
    const matchKey = matchKeys[0];
    return dynamicViewsModules[matchKey];
  } else if (matchKeys?.length > 1) {
    warn(
      'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure'
    );
    return;
  } else {
    // TODO exception page

    warn('在src/views/下找不到`' + component + '.vue` 或 `' + component + '.tsx`, 请自行创建!');
    return;
  }
}

/* eslint-disable */
export const PARENT_LAYOUT_NAME = 'ParentLayout';
export const getParentLayout = (_name?: string) => {
  return () =>
    new Promise((resolve) => {
      resolve({
        name: PARENT_LAYOUT_NAME,
      });
    });
};
/* eslint-disable */

function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
  dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}');
  if (!routes) return;
  routes.forEach((item) => {
    if (!item.component && item.meta?.frameSrc) {
      item.component = 'IFRAME';
    }
    const { component, name } = item;
    const { children } = item;
    if (component) {
      const layoutFound = LayoutMap.get(component.toUpperCase());
      if (layoutFound) {
        item.component = layoutFound;
      } else {
        item.component = dynamicImport(dynamicViewsModules, component as string);
      }
    } else if (name) {
      item.component = getParentLayout();
    }
    children && asyncImportRoute(children);
  });
}

export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
  routeList.forEach((route) => {
    const component = route.component as string;
    if (component) {
      if (component.toUpperCase() === 'LAYOUT') {
        route.component = LayoutMap.get(component.toUpperCase());
      } else {
        route.children = [cloneDeep(route)];
        route.component = LAYOUT;
        route.name = `${route.name}Parent`;
        route.path = '';
        const meta = route.meta || {};
        meta.single = true;
        meta.affix = false;
        route.meta = meta;
      }
    } else {
      warn('请正确配置路由：' + route?.name + '的component属性');
    }
    route.children && asyncImportRoute(route.children);
  });
  return routeList as unknown as T[];
}

function isMultipleRoute(routeModule: AppRouteModule) {
  if (!routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length) {
    return false;
  }

  const children = routeModule.children;

  let flag = false;
  for (let index = 0; index < children.length; index++) {
    const child = children[index];
    if (child.children?.length) {
      flag = true;
      break;
    }
  }
  return flag;
}
// Add all sub-routes to the secondary route
function addToChildren(routes: RouteRecordNormalized[], children: AppRouteRecordRaw[], routeModule: AppRouteModule) {
  for (let index = 0; index < children.length; index++) {
    const child = children[index];
    const route = routes.find((item) => item.name === child.name);
    if (!route) {
      continue;
    }
    routeModule.children = routeModule.children || [];
    if (!routeModule.children.find((item) => item.name === route.name)) {
      routeModule.children?.push(route as unknown as AppRouteModule);
    }
    if (child.children?.length) {
      addToChildren(routes, child.children, routeModule);
    }
  }
}

function promoteRouteLevel(routeModule: AppRouteModule) {
  // Use vue-router to splice menus
  let router: Router | null = createRouter({
    routes: [routeModule as unknown as RouteRecordNormalized],
    history: createWebHashHistory(),
  });

  const routes = router.getRoutes();
  addToChildren(routes, routeModule.children || [], routeModule);
  router = null;

  routeModule.children = routeModule.children?.map((item) => omit(item, 'children'));
}

export function flatMultiLevelRoutes(routeModules: AppRouteModule[]) {
  const modules: AppRouteModule[] = cloneDeep(routeModules);
  for (let index = 0; index < modules.length; index++) {
    const routeModule = modules[index];
    if (!isMultipleRoute(routeModule)) {
      continue;
    }
    promoteRouteLevel(routeModule);
  }
  return modules;
}

function replaceProperty(route: AppRouteRecordRaw) {
  let { routePath, meta, redirectPath, ...rest } = route;
  let { ifHideBreadcrumb, ifHideMenu, ifHideChildrenMenu, ...metaRest } = meta;
  const newRoute = {
    path: routePath,
    redirect: redirectPath,
    meta: {
      hideBreadcrumb: ifHideBreadcrumb,
      hideMenu: ifHideMenu,
      hideChildrenMenu: ifHideChildrenMenu,
      ...metaRest,
    },
    ...rest,
  };
  return newRoute;
}
export function replaceList(routeList: AppRouteRecordRaw[]) {
  for (let i = 0; i < routeList.length; i++) {
    routeList[i] = replaceProperty(routeList[i]);
    if (routeList[i].children) {
      replaceList(routeList[i].children as AppRouteRecordRaw[]);
    }
  }
  return routeList;
}

export function getHomePathAndAddRoutes(routes: AppRouteRecordRaw[], router: Router) {
  let homePath: string = '';
  routes.forEach((route) => {
    router.addRoute(route as unknown as RouteRecordRaw);
    switch (route.path) {
      case SaaSPageEnum.ORDER_MGMT:
      case SaaSPageEnum.COMMODITY_MGMT:
        if (!homePath) {
          homePath = route.path;
        }
        break;

      case SaaSPageEnum.INSTANCE_PURCHASE:
        if (!homePath) {
          // 若同时存在首页及套餐购买权限，优先首页
          homePath = route.path;
        }
        break;
      case SaaSPageEnum.TENANT_HOMEPAGE:
      case SaaSPageEnum.PLATFORM_HOEMPAGE:
        homePath = route.path;
        break;

      default:
        if (!homePath && route !== PAGE_NOT_FOUND_ROUTE) {
          homePath = route.path;
        }
        break;
    }
  });
  router.addRoute(PAGE_NOT_FOUND_ROUTE as unknown as RouteRecordRaw);
  return homePath;
}

export function importFrontendRoutes(backMenuList: Menu[], menu: Menu) {
  backMenuList.push(menu);
}

export const userInfoRoute: Menu = {
  hideBreadcrumb: false,
  hideMenu: true,
  title: 'routes.userInfo.userInfo',
  orderNo: 1,
  icon: 'ant-design:home-outlined',
  ifHideChildrenInMenu: true,
  breadcrumbName: 'routes.homepage.homepage',
  meta: {
    hideBreadcrumb: false,
    hideMenu: true,
    title: 'routes.homepage.homepage',
    orderNo: 1,
    icon: 'ant-design:home-outlined',
    ifHideChildrenInMenu: true,
  },
  name: 'routes.userInfo.userInf',
  pathAndTitle: '/platformHome^routes.homepage.homepage',
  path: '/userInfo',
  redirect: '/userInfo',
  children: [
    {
      hideMenu: true,
      title: 'routes.userInfo.userInfo',
      orderNo: 100,
      icon: 'ant-design:home-outlined',
      ifHideChildrenInMenu: false,
      breadcrumbName: 'routes.userInfo.userInfo',
      meta: {
        hideBreadcrumb: false,
        hideMenu: true,
        title: 'routes.userInfo.userInfo',
        orderNo: 100,
        icon: 'ant-design:home-outlined',
        ifHideChildrenInMenu: false,
      },
      name: 'routes.userInfo.userInfo',
      pathAndTitle: 'index^routes.homepage.homepage',
      path: '/userInfo',
    },
  ],
};
